#ifndef _TRIPLE_H_
#define _TRIPLE_H_

////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////////////////////

namespace Types {

////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////

/**
 *  Generic triple class.
 *	This class creates a generic triple.
 */
template <typename T1, typename T2, typename T3>
class Triple {

	public:

		/// Triple creation with default values
		Triple() {}

		/// Triple creation with initialisation values
		Triple(
			const T1 & first,
			const T2 & second,
			const T3 & third
		) : first(first), second(second), third(third) {}

		/// Create a copy of the given instance
		template <typename OT1, typename OT2, typename OT3>
		Triple(const Triple<OT1,OT2,OT3> & inst)
		:	first(static_cast<T1>(inst.GetFirst())),
			second(static_cast<T2>(inst.GetSecond())),
			third(static_cast<T3>(inst.GetThird()))
		{}
		
		/// Affectation operator
		template <typename OT1, typename OT2, typename OT3>
		Triple<T1,T2,T3> & operator = (const Triple<OT1,OT2,OT3> & inst) {
			if (this != &inst) {
				this->first		= static_cast<T1>(inst.GetFirst());
				this->second	= static_cast<T2>(inst.GetSecond());
				this->third		= static_cast<T3>(inst.GetThird());
			}
			return *this;
		}
		
		/// Returns the first value
		inline T1 & First() { return this->first; }
		inline const T1 & GetFirst() const { return this->first; }
		
		/// Returns the second value
		inline T2 & Second() { return this->second; }
		inline const T2 & GetSecond() const { return this->second; }
		
		/// Returns the third value
		inline T3 & Third() { return this->third; }
		inline const T3 & GetThird() const { return this->third; }
		
	protected:
		
		/// First value
		T1 first;
		
		/// Second value
		T2 second;
		
		/// Third value
		T3 third;

};

////////////////////////////////////////////////////////////////////////////////
// Closing Namespaces
////////////////////////////////////////////////////////////////////////////////

}

////////////////////////////////////////////////////////////////////////////////

#endif
